package gui 
{
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import gui.buttons.BaseButton;
	import gui.buttons.LabelButton;
	import utils.Logger;
	/**
	 * ...
	 * @author Dmitriy Gaiduk
	 */
	public class ScrollBar extends Sprite
	{
		private var _width:Number = 20;
		private var _height:Number = 150;
		
		private var _minusButton:InteractiveObject ;
		private var _plusButton:InteractiveObject;
		private var _scrollBar:DisplayObject;
		private var _thumb:InteractiveObject;
		private var _type:String;
		
	
		public static const HORIZONTAL:String = "horizontal";
		public static const VERTICAL:String = "vertical";
		
		protected var _isInvalidation:Boolean = false;
		
		private var _xOffset:Number;
		private var _yOffset:Number;
		
		private var _minusBtnPos:PositionInfo;
		private var _plusBtnPos:PositionInfo;
		private var _scrollBarPos:PositionInfo;
		
		private var _thumbPos:PositionInfo;
		private var _thumbBounds:Rectangle;
		private var _scrollPercent:Number = 0;
		//private var _stepPercent:Number = 0.05;
		private var _autoScrollStep:Number;
		private var _scrollStep:Number = 0.02;
		
	
		
		public function ScrollBar() 
		{
			type = VERTICAL;
			addEventListener(Event.ADDED_TO_STAGE, handleAddedTostage);
		}
		
		private function handleAddedTostage(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, handleAddedTostage);
			
			initScrollBar();
		}
		
		private function initScrollBar():void 
		{
			_minusBtnPos = new PositionInfo();
			_plusBtnPos = new PositionInfo();
			_scrollBarPos = new PositionInfo();
			_thumbPos = new PositionInfo();
			_thumbBounds = new Rectangle();
			
			var size:Number = 15;
			
			if (_minusButton == null)
			{
				minusButton = new LabelButton();
				(minusButton as LabelButton).label = "/\\";
				minusButton.width = size;
				minusButton.height = size;
			}
			_minusButton.addEventListener(MouseEvent.MOUSE_DOWN, handleUpButtonMouseDown);
			
			if (_plusButton == null)
			{
				plusButton = new LabelButton();
				(plusButton as LabelButton).label = "\\/";
				plusButton.width = size;
				plusButton.height = size;
			}
			_plusButton.addEventListener(MouseEvent.MOUSE_DOWN, handleDownButtonMouseDown);
			
			/*if (_thumb == null)
			{
				thumb = new BaseButton();
				thumb.width = size;
				thumb.height = size;
			}
			_thumbBounds.left = 0;
			_thumbBounds.top = _plusButton.height;
			_thumbBounds.bottom = height - downButton.height - _thumb.height;
			*/
			
			invalidate();
			//var gr:Graphics = graphics;
			//gr.lineStyle(1);
			//gr.drawRect(0, 0, width, height);
		}
		
		private function handleDownButtonMouseDown(e:MouseEvent):void 
		{
			//scrollPercent += _stepPercent;
			_autoScrollStep = _scrollStep;
			stage.addEventListener(Event.ENTER_FRAME, autoScroll);
			stage.addEventListener(MouseEvent.MOUSE_UP, stopAutoScroll);
		}
		
		private function handleUpButtonMouseDown(e:MouseEvent):void 
		{
			//scrollPercent -= _stepPercent;
			_autoScrollStep = -_scrollStep;
			stage.addEventListener(Event.ENTER_FRAME, autoScroll);
			stage.addEventListener(MouseEvent.MOUSE_UP, stopAutoScroll);
		}
		
		private function stopAutoScroll(e:MouseEvent):void 
		{
			stage.removeEventListener(Event.ENTER_FRAME, autoScroll);
			stage.removeEventListener(MouseEvent.MOUSE_UP, stopAutoScroll);
		}
		
		private function autoScroll(e:Event):void 
		{
			scrollPercent += _autoScrollStep;
		}
		
		
		
		public function invalidate():void
		{
			if (!_isInvalidation)
			{
				_isInvalidation = true;
				addEventListener(Event.ENTER_FRAME, onInvalidate);
			}
		}
		
		
		protected function onInvalidate(e:Event):void 
		{
			removeEventListener(Event.ENTER_FRAME, onInvalidate);
			_isInvalidation = false;
			updateView();
		}
		
		private function updateView():void 
		{
			switch(type)
			{
				case VERTICAL:
						_minusBtnPos.align = PositionInfo.ALIGN_CENTR_X;
						_minusBtnPos.posX = 0;
						
						_plusBtnPos.align = PositionInfo.ALIGN_CENTR_X;
						_plusBtnPos.addAlign(PositionInfo.ALIGN_BOTTOM);
						_plusBtnPos.bottomPadding = 0;
						
						_scrollBarPos.align = PositionInfo.ALIGN_CENTR_X;
						_scrollBarPos.addAlign(PositionInfo.ALIGN_CENTR_Y);
						
						_thumbPos.align = PositionInfo.ALIGN_CENTR_X;
						_thumbBounds.bottom = height -  plusButton.height - _thumb.height;
						_thumbBounds.top = minusButton.x + minusButton.height;
					break;
				case HORIZONTAL:
						_minusBtnPos.align = PositionInfo.ALIGN_CENTR_Y;
						_minusBtnPos.posX = 0;
						
						_plusBtnPos.align = PositionInfo.ALIGN_CENTR_Y;
						_plusBtnPos.addAlign(PositionInfo.ALIGN_RIGHT);
						_plusBtnPos.rightPadding = 0;
						
						_scrollBarPos.align = PositionInfo.ALIGN_CENTR_Y;
						//_scrollBarPos.addAlign(PositionInfo.ALIGN_CENTR_Y);
					break;
			}
			
			setPosition(_plusButton, _plusBtnPos);
			setPosition(_minusButton, _minusBtnPos);
			setPosition(_scrollBar, _scrollBarPos);
			checkThumbPos();
			setPosition(_thumb, _thumbPos);
			
			//log("up btn y: " + _plusButton.y + " w: " + _plusButton.width);
			//log("_downButton btn y: " + _downButton.y + " w: " + _downButton.width);
			//log("height: " + height);
		}
		
		private function checkThumbPos():void 
		{
			if (_thumb == null)
			{
				return;
			}
			
			if (_thumbPos.posY > _thumbBounds.bottom)
			{
				_thumbPos.posY = _thumbBounds.bottom;
			}
			if (_thumbPos.posY < _thumbBounds.top)
			{
				_thumbPos.posY = _thumbBounds.top;
			}
		}
		
		private function setPosition(obj:DisplayObject, pos:PositionInfo):void 
		{
			if (obj != null && pos != null)
			{
				obj.x = pos.getPosX(width, obj.width);
				obj.y = pos.getPosY(height, obj.height);
			}
		}
		
		override public function get width():Number 
		{
			return _width;
		}
		
		override public function set width(value:Number):void 
		{
			_width = value;
		}
		
		override public function get height():Number 
		{
			return _height;
		}
		
		override public function set height(value:Number):void 
		{
			_height = value;
			invalidate();
		}
		
	
		
	
		
		public function get thumb():InteractiveObject 
		{
			return _thumb;
		}
		
		public function set thumb(value:InteractiveObject):void 
		{
			_thumb = value;
			if (_thumb != null)
			{
				_thumb.addEventListener(MouseEvent.MOUSE_DOWN, hamdleThumbMouseDown);
				addChild(_thumb);
			}
		}
		
		private function hamdleThumbMouseDown(e:MouseEvent):void 
		{
			_yOffset =  mouseY - _thumb.y;
			_xOffset =  mouseX - _thumb.x;
			stage.addEventListener(MouseEvent.MOUSE_MOVE, handleStageMouseMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
		}
		
		private function handleStageMouseUp(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleStageMouseMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
			
		}
		
		private function handleStageMouseMove(e:MouseEvent):void 
		{
			 _thumbPos.posX = mouseX - _xOffset;
			 _thumbPos.posY = mouseY - _yOffset;
			 checkThumbPos();
			// _thumb.y = mouseY - _yOffset;
			// _thumb.x = mouseX - _xOffset;
			if (_thumbBounds.height != 0)
			{
				scrollPercent = (_thumbPos.posY - _thumbBounds.top) / _thumbBounds.height;
				//trace("Percent: " + _scrollPercent);
			}
			 setPosition(_thumb, _thumbPos);
			 e.updateAfterEvent();
		}
		
		public function get type():String 
		{
			return _type;
		}
		
		public function set type(value:String):void 
		{
			_type = value;
			invalidate();
			//setupZumbPos();
		}
		
		public function get scrollPercent():Number 
		{
			return _scrollPercent;
		}
		
		public function set scrollPercent(value:Number):void 
		{
			if (_scrollPercent != value)
			{
				_scrollPercent = value;
				if (_scrollPercent < 0)
				{
					_scrollPercent = 0;
				}else if (_scrollPercent > 1)
				{
					_scrollPercent = 1;
				}
				updateThumb();
				dispatchEvent(new Event(Event.CHANGE));
			}
		}
		
		public function get scrollBar():DisplayObject 
		{
			return _scrollBar;
		}
		
		public function set scrollBar(value:DisplayObject):void 
		{
			_scrollBar = value;
			switch(type)
			{
				case VERTICAL:
						
					break;
			}
			addChild(_scrollBar);
		}
		
		public function get scrollStep():Number 
		{
			return _scrollStep;
		}
		
		public function set scrollStep(value:Number):void 
		{
			_scrollStep = value;
		}
		
		public function get minusButton():InteractiveObject 
		{
			return _minusButton;
		}
		
		public function set minusButton(value:InteractiveObject):void 
		{
			_minusButton = value;
			if (_minusButton != null)
			{
				addChild(_minusButton);
			}
		}
		
		public function get plusButton():InteractiveObject 
		{
			return _plusButton;
		}
		
		public function set plusButton(value:InteractiveObject):void 
		{
			_plusButton = value;
			if (_plusButton != null)
			{
				addChild(_plusButton);
			}
		}
		
		
		
		private function setupZumbPos():void
		{
			switch(type)
			{
				case VERTICAL:
						_thumbPos.align = PositionInfo.ALIGN_CENTR_X;
						
					break;
			}
			updateThumb();
		}
		
		private function updateThumb():void
		{
			switch(type)
			{
				case VERTICAL:
						 _thumbPos.posY = scrollPercent * _thumbBounds.height + _thumbBounds.top;
					break;
			}
			
			checkThumbPos();
			setPosition(_thumb, _thumbPos);
		}
		
		public function silentSetValue(percent:Number):void
		{
			if (_scrollPercent != percent && percent>=0 && percent<=1)
			{
				_scrollPercent = percent;
				updateThumb();
			}
		}
		
		private function log(msg:String):void
		{
			Logger.log(this, msg);
		}
		
	}

}